import {
  DragAndDropProvider,
  DraggableItem,
  DragHandle,
  DroppableContainer,
  Icon,
  useCall,
  useSet,
} from '@/components';
import { Button, Table } from 'antd';
import React, { useState } from 'react';
import data from './data.json';

const columns = [
  {
    key: 'sorter',
    title: '排序',
    width: 64,
    render() {
      return (
        <DragHandle>
          <Button size='small' type='text'>
            <Icon type='menu' />
          </Button>
        </DragHandle>
      );
    },
  },
  { dataIndex: 'benefitCode', title: 'benefitCode' },
  { dataIndex: 'benefitName', title: 'benefitName' },
];

const components = {
  table: 'table',
  body: {
    wrapper: DroppableContainer,
    row: DraggableItem,
    cell: 'td',
  },
};

function Example(props) {
  const [dataSource, setDataSource] = useState(data);
  const onRow = useCall((row, index) => ({ row, index }));
  const [expandedKeys, expandedMisc] = useSet([], true);

  const expandable = {
    expandedRowKeys: expandedKeys,
    onExpandedRowsChange: expandedMisc.set,
    rowExpandable: useCall((row) => row.children?.length > 0),
    expandIconColumnIndex: 1,
  };

  const getDroppableKeys = useCall((allCtxMap, draggingCtx) => {
    const draggingRowKey = draggingCtx.row.id;
    const allPairs = Array.from(allCtxMap);
    const childrenKeys = [];
    const parentPair = allPairs.find(([_, { row }]) => {
      childrenKeys.push(...row.children.map((v) => v.id));
      return row.children?.some((v) => v.id === draggingRowKey);
    });

    let droppableKeys = [];
    if (!parentPair) {
      droppableKeys = allPairs.reduce((ret, [key]) => ret.concat(childrenKeys.includes(key) ? [] : [key]), []);
    } else {
      droppableKeys = parentPair[1].row.children.map((v) => v.id);
    }
    const nextExpanded = expandedKeys.filter((v) => !droppableKeys.includes(v));
    setTimeout(expandedMisc.set, 0, nextExpanded);
    return droppableKeys;
  });

  const onDrop = useCall((itemCtx, index, allCtxMap) => {
    const itemRowKey = itemCtx.row.id;
    const allPairs = Array.from(allCtxMap);
    const parentPair = allPairs.find(([_, { row }]) => {
      return row.children?.some((v) => v.id === itemRowKey);
    });
    if (!parentPair) {
      setDataSource((prev) => {
        const next = prev.slice();
        const [item] = next.splice(itemCtx.index, 1);
        next.splice(index, 0, item);
        return next;
      });
    } else {
      const parentRow = parentPair[1].row;
      parentRow.children = parentRow.children.slice();
      const [item] = parentRow.children.splice(itemCtx.index, 1);
      parentRow.children.splice(index, 0, item);
      setDataSource(dataSource.slice());
    }
  });

  return (
    <DragAndDropProvider
      rowKey='id'
      itemComponent='tr'
      itemDraggingClassName='ant-table-row-selected'
      containerComponent='tbody'
      getDroppableKeys={getDroppableKeys}
      onDrop={onDrop}
    >
      <Table
        rowKey='id'
        onRow={onRow}
        components={components}
        expandable={expandable}
        dataSource={dataSource}
        columns={columns}
      />
    </DragAndDropProvider>
  );
}

export default Example;
